﻿using System;
using System.IO;
using System.Security.Cryptography;
using System.Text;

namespace Web7.Utilities
{
    public class SymmetricEncrypt
    {
        private SymmetricEncryptType encryptionType;
        private SymmetricAlgorithm CSP;
        private string strEncryptedString;
        private string strOriginalString;

        public SymmetricEncrypt()
        {
            this.encryptionType = SymmetricEncryptType.DES;
            this.SetEncryptor();
        }

        public SymmetricEncrypt(SymmetricEncryptType encryptionType)
        {
            this.encryptionType = encryptionType;
            this.SetEncryptor();
        }

        public SymmetricEncrypt(SymmetricEncryptType encryptionType, string originalString)
        {
            this.encryptionType = encryptionType;
            this.strOriginalString = originalString;
            this.SetEncryptor();
        }

        public string Decrypt()
        {
            ICryptoTransform transform = this.CSP.CreateDecryptor(this.CSP.Key, this.CSP.IV);
            byte[] buffer = Convert.FromBase64String(this.strEncryptedString);
            MemoryStream stream = new MemoryStream();
            CryptoStream stream2 = new CryptoStream(stream, transform, CryptoStreamMode.Write);
            stream2.Write(buffer, 0, buffer.Length);
            stream2.FlushFinalBlock();
            stream2.Close();
            this.strOriginalString = Encoding.Unicode.GetString(stream.ToArray());
            return this.strOriginalString;
        }

        public string Decrypt(string encryptedString)
        {
            this.strEncryptedString = encryptedString;
            return this.Decrypt();
        }

        public string Decrypt(string encryptedString, SymmetricEncryptType encryptionType)
        {
            this.strEncryptedString = encryptedString;
            this.encryptionType = encryptionType;
            return this.Decrypt();
        }

        public string Encrypt()
        {
            ICryptoTransform transform = this.CSP.CreateEncryptor(this.Key, this.IV);
            byte[] bytes = Encoding.Unicode.GetBytes(this.strOriginalString);
            MemoryStream stream = new MemoryStream();
            CryptoStream stream2 = new CryptoStream(stream, transform, CryptoStreamMode.Write);
            stream2.Write(bytes, 0, bytes.Length);
            stream2.FlushFinalBlock();
            stream2.Close();
            this.strEncryptedString = Convert.ToBase64String(stream.ToArray());
            return this.strEncryptedString;
        }

        public string Encrypt(string originalString)
        {
            this.strOriginalString = originalString;
            return this.Encrypt();
        }

        public string Encrypt(string originalString, SymmetricEncryptType encryptionType)
        {
            this.strOriginalString = originalString;
            this.encryptionType = encryptionType;
            return this.Encrypt();
        }

        public string GenerateIV()
        {
            this.CSP.GenerateIV();
            return Convert.ToBase64String(this.CSP.IV);
        }

        public string GenerateKey()
        {
            this.CSP.GenerateKey();
            return Convert.ToBase64String(this.CSP.Key);
        }

        private void SetEncryptor()
        {
            switch (this.encryptionType)
            {
                case SymmetricEncryptType.DES:
                    this.CSP = new DESCryptoServiceProvider();
                    break;

                case SymmetricEncryptType.RC2:
                    this.CSP = new RC2CryptoServiceProvider();
                    break;

                case SymmetricEncryptType.Rijndael:
                    this.CSP = new RijndaelManaged();
                    break;

                case SymmetricEncryptType.TripleDES:
                    this.CSP = new TripleDESCryptoServiceProvider();
                    break;
            }
            this.CSP.GenerateKey();
            this.CSP.GenerateIV();
        }

        public SymmetricAlgorithm CryptoProvider
        {
            get
            {
                return this.CSP;
            }
            set
            {
                this.CSP = value;
            }
        }

        public string EncryptedString
        {
            get
            {
                return this.strEncryptedString;
            }
            set
            {
                this.strEncryptedString = value;
            }
        }

        public SymmetricEncryptType EncryptionType
        {
            get
            {
                return this.encryptionType;
            }
            set
            {
                if (this.encryptionType != value)
                {
                    this.encryptionType = value;
                    this.strOriginalString = string.Empty;
                    this.strEncryptedString = string.Empty;
                    this.SetEncryptor();
                }
            }
        }

        public byte[] IV
        {
            get
            {
                return this.CSP.IV;
            }
            set
            {
                this.CSP.IV = value;
            }
        }

        public string IVString
        {
            get
            {
                return Convert.ToBase64String(this.CSP.IV);
            }
            set
            {
                this.CSP.IV = Convert.FromBase64String(value);
            }
        }

        public byte[] Key
        {
            get
            {
                return this.CSP.Key;
            }
            set
            {
                this.CSP.Key = value;
            }
        }

        public string KeyString
        {
            get
            {
                return Convert.ToBase64String(this.CSP.Key);
            }
            set
            {
                this.CSP.Key = Convert.FromBase64String(value);
            }
        }

        public string OriginalString
        {
            get
            {
                return this.strOriginalString;
            }
            set
            {
                this.strOriginalString = value;
            }
        }
    }
}
